﻿using System;
using System.Collections.Generic;
using FieldDevice.ModBus;
using FieldLib;
using FieldDevice;
namespace FieldDevice.Emulation
{
    public class PM800Emulator : DeviceEmulator
    {
        public PM800Emulator(ushort address)
            :base(address)
        {
            this.timeEmulation = new System.Windows.Forms.Timer();
            this.timeEmulation.Enabled = true;
            this.timeEmulation.Interval = 1000;
            this.timeEmulation.Tick += new EventHandler(this.timeEmulation_tick);
            DataEmulator = new DataEmulatorForm(address);
            DataEmulator.Show();
        }
        DataEmulatorForm DataEmulator;
        private System.Windows.Forms.Timer timeEmulation;

         /*
         * 
         * 由于软件编程时是以1为基址，而仪表以
         * 0为基址，因此软件中的
         * 寄存器地址在说明书（参见PM800-用户手册)
         * 中寄存器地址的基础上减1
         *          
         */

        public const ushort ADDR1100_Ia=1099;       //A相电流
        public const ushort ADDR1101_Ib = 1100;     //B相电流
        public const ushort ADDR1102_Ic = 1101;     //C相电流
        //public const ushort ADDR1103_Neu = 1102;    //中性线电流

        public const ushort ADDR1120_Vab = 1119;    //A-B线电压地址
        public const ushort ADDR1121_Vbc = 1120;    //B-C线电压地址
        public const ushort ADDR1122_Vca = 1121;    //C-A线电压地址
        //public const ushort ADDR1123_Ave = 1122;     //线电压平均值   
        
        public const ushort ADDR1124_Va = 1123;     //A相电压地址
        public const ushort ADDR1125_Vb = 1124;     //B相电压地址
        public const ushort ADDR1126_Vc = 1125;     //C相电压地址

        public const ushort ADDR1143_P_Hi = 1142;          //总有功功率高位
        public const ushort ADDR1144_P_Low = 1143;      //总有功功率低位
        public const ushort ADDR1147_Q_Hi = 1146;          //总无功功率
        public const ushort ADDR1148_Q_Low = 1147;     //总无功功率低位
        public const ushort ADDR1151_S_Hi = 1150;          //总视在功率高位
        public const ushort ADDR1152_S_Low = 1151;          //总视在功率低位

        public const ushort ADDR1180_F = 1179;          //频率
        public const ushort ADDR_Kwh = 1725;            //总有功电度
        public const ushort ADDR_Kvarh = 1719;          //总无功电度


        public short Register_Ia;       //寄存A相电流
        public short Register_Ib;       //寄存B相电流
        public short Register_Ic;       //寄存C相电流

        public short Register_Va;       //寄存A相电压
        public short Register_Vb;       //寄存B相电压
        public short Register_Vc;       //寄存C相电压

        byte[] ModBuffer = new byte[1 + 2 + 2 + 256 * 2 + 2 + 2 + 1];
        int DataLen;

        public override byte[] ProcessModBusPacket(ModBusPacket packet)
        {
            ModBusPacket tmpPacket = packet;
            tmpPacket = CRCVerify(tmpPacket);
            if (packet.CRCH != tmpPacket.CRCH || packet.CRCL != tmpPacket.CRCL)
            {
                packet.DataNumberHi = 0x00;
                packet.DataNumberLow = 0x00;
            }

            switch (packet.Function)
            {
                case ModBus.ModBusFunction.READHOLDINGREGISTER:
                    ReadRegister(packet);
                    break;
                default:
                    break;
            }
            packet = CRCVerify(packet);
            ModBuffer[2 * DataLen + 3] = packet.CRCH;
            ModBuffer[2 * DataLen + 4] = packet.CRCL;
            return ModBuffer;
                
        }

        public void ReadRegister(ModBusPacket input)
        {
            ushort tmpAddressData;
            short tmpData;
            tmpAddressData = input.DataAddressHi;
            tmpAddressData <<= 8;
            tmpAddressData += input.DataAddressLow;
            DataLen = input.DataNumberHi;
            DataLen <<= 8;
            DataLen += input.DataNumberLow;
            ModBuffer[2] = (byte)DataLen;
            for (int i = 0; i < DataLen; i++)
            {
                tmpData = RegisterValue(tmpAddressData + i);
                ModBuffer[2 * i + 3] = (byte)(tmpData >> 8);
                ModBuffer[2 * i + 4] = (byte)(tmpData & 0xff);
            }
        }

        private short RegisterValue(int addr)
        {
            short value = 0;
            switch (addr)
            {
                case ADDR1100_Ia:
                    value = Register_Ia;
                    break;
                case ADDR1101_Ib:
                    value = Register_Ib;
                    break;
                case ADDR1102_Ic:
                    value = Register_Ic;
                    break;
                case ADDR1124_Va:
                    value = Register_Va;
                    break;
                case ADDR1125_Vb:
                    value = Register_Vb;
                    break;
                case ADDR1126_Vc:
                    value = Register_Vc;
                    break;
                default:
                    break;


            }
            return value;

        }


        private void timeEmulation_tick(object sender, EventArgs e)
        {
            Random randomNum = new Random();
            this.Register_Ia = (short)randomNum.Next(500);
            DataEmulator.IA = Convert.ToString( this.Register_Ia);
            this.Register_Ib = (short)randomNum.Next(500);
            DataEmulator.IB = Convert.ToString(this.Register_Ib);
            this.Register_Ic = (short)randomNum.Next(500);
            DataEmulator.IC = Convert.ToString(this.Register_Ic);


            this.Register_Va = (short)randomNum.Next(35000);
            DataEmulator.VA = Convert.ToString(this.Register_Va);
            this.Register_Vb = (short)randomNum.Next(35000);
            DataEmulator.VB = Convert.ToString(this.Register_Vb);
            this.Register_Vc = (short)randomNum.Next(35000);
            DataEmulator.VC = Convert.ToString(this.Register_Vc);
        }
        
    }
}
